<template>
    <div ref="divRef" class="content">
        <div class="left" v-if="configs?.leftConfig">
            <!-- 左侧选项配置 -->
            <el-card>
                <el-menu v-bind="configs.leftConfig.menuConfig" :default-active="defaultActive" @select="select">
                    <el-menu-item v-for="config in configs.leftConfig.menuItemConfig" :index="config.index">
                        <h3>{{ config.title }}</h3>
                    </el-menu-item>
                </el-menu>
            </el-card>
        </div>
        <div class="right">
            <!-- 右侧表单配置 -->
            <el-card v-for="config in configData">
                <!-- tabs标签页 -->
                <slot :index="index"></slot>
                <p style="font-size: 20px;">{{ config.header }}</p>
                <!-- form：el-form配置  -->
                <el-form v-for="form in config.ElForm" v-bind="filterProps(form)" :disabled="!modelValue">
                    <!-- form 标题 -->
                    <p v-if="form.title">{{ form.title }}</p>
                    <!-- formItem：el-form-item 配置 -->
                    <el-form-item v-for="formItem in form.children" v-bind="filterProps(formItem)">
                        <!-- item：el-form-item 内表单配置 -->
                        <template v-for="item in formItem.children">
                            <el-switch v-if="item?.type == 'switch'" v-bind="item"
                                v-model="(form.model as any)[item.model]"></el-switch>
                            <el-select v-else-if="item?.type == 'select'" v-bind="filterProps(item)"
                                v-model="(form.model as any)[item.model]">
                                <slot :name="item.name ?? 'select'"></slot>
                            </el-select>
                            <template v-else>
                                <!-- 有inputIsNum 表示需要输入为数值类型数据，因为不能传递修饰符原因，只能通过标识处理 -->
                                <el-input v-if="item.inputIsNum" v-bind="item"
                                    v-model.number.trim="(form.model as any)[(item.model)]"></el-input>
                                <el-input v-else v-bind="item" v-model.trim="(form.model as any)[(item.model)]"></el-input>
                            </template>
                        </template>
                    </el-form-item>
                </el-form>
                <template v-if="modelValue">
                    <el-button @click="methods.Cancel(index)">取消</el-button>
                    <el-button type="primary" @click="methods.SubmitForm(index)">提交</el-button>
                </template>
                <el-button v-else type="primary" @click="emit('update:modelValue', true)">编辑</el-button>
            </el-card>
        </div>
    </div>
</template>

<script setup lang="ts">
import { computed, ref, onMounted } from 'vue'
import { leftConfigType, formConfigType } from "./Type"

interface PropsType {
    /** 
     * 配置：{ leftConfig：左侧选项配置，formConfig：右侧表单配置 }
     *  */
    configs: {
        leftConfig?: leftConfigType,
        formConfig: formConfigType,
    }
    /** 是否编辑状态 */
    modelValue: boolean,
    /** 
     * 方法：{Cancel：取消，SubmitForm：提交}
     *  */
    methods: {
        Cancel: (index: string) => void,
        SubmitForm: (index: string) => void
    },
    /**
     *  配置的样式：{ width：设置宽度，minWidth：最小宽度 }
     */
    styles?: {
        /** [左侧，右侧] */
        width?: [string, string],
        /** [左侧，右侧] */
        minWidth?: [`${number}px`, `${number}px`]
    }
}

const props = defineProps<PropsType>()
const emit = defineEmits(["update:modelValue"])

// 默认激活项
const defaultActive = computed(() => {
    return props.configs.leftConfig?.menuConfig?.['default-active'] ?? "0"
})

// 默认样式
const styles = computed(() => {
    return {
        // 设置默认值 在多级对象结构下用withDefaults不生效
        width: props.styles?.width ?? ["20%", "40%"],
        minWidth: props.styles?.minWidth ?? ["200px", "350px"]
    }
})

// 过滤children 去除 warn 警告
const filterProps = ((obj: any) => {
    const newObj = { ...obj };
    delete newObj.title;
    delete newObj.children;
    delete newObj.name;
    return newObj;
})

const index = ref(defaultActive.value || "0")
const select = (i: string) => {
    if (index.value == i) {
        return
    }
    props.methods.Cancel(index.value)
    index.value = i
}

// 当前选中项数据
const configData = computed(() => {
    return [props.configs.formConfig?.[+index.value]] ?? []
})

const divRef = ref<HTMLDivElement>()
// 数据展示方式
const flexCss = ref<"none" | "1">("none")

onMounted(() => {
    // 监听大容器变化（相比window监听整个窗口变化，该方法只会监听当前容器变化）
    let r = styles.value?.minWidth?.map((item) => parseInt(item)).reduce((n, val) => {
        return n + val
    }, 0) || 0

    const resizeObserver = new ResizeObserver(entries => {
        for (let entry of entries) {
            if (entry.contentRect.width < (r + 30 + 16)) {
                flexCss.value = "1"
            } else {
                flexCss.value = 'none'
            }
        }
    });

    divRef.value && resizeObserver.observe(divRef.value);
})

</script>

<style lang="scss" scoped>
.content {
    display: flex;
    flex-wrap: wrap;

    &>div {
        flex: v-bind("flexCss");
        margin-right: 15px;
        transition: width .5s;
    }

    .left {
        width: v-bind("styles?.width?.[0]");
        min-width: v-bind("styles?.minWidth?.[0]");

        .el-menu {
            border: 0;

            .is-active {
                background-color: #ecf5ff;
            }
        }
    }

    .right {
        width: v-bind("styles?.width?.[1]");
        min-width: v-bind("styles?.minWidth?.[1]");

        p {
            margin: 0 0 10px;
            font-weight: bold;
        }
    }
}
</style>